"""
Help support pygments so we don't break when using the wrong
mimetype.

APPLICATION_MIMES - Mimes which are reported by libmagic in the format
    "text/..." instead of "application/...".
TEXT_MIMES - Mimes which are reported by libmagic in the format "application/..."
    instead of "text/...".
PLAINTEXT_MIMES - Mimes which are reported by libmagic with "application/...", but
    are actually representable with text.
"""

# This file licensed under the Affero GNU Public License, Version 3 or Later.
# See ../LICENSES/LICENSE-AGPL for details

from pygments.lexers import get_lexer_for_mimetype
from pygments.util import ClassNotFound


# files that have "text/..." mimes instead of "application/..."
APPLICATION_MIMES = ('x-shellscript', 'x-php', 'x-sh', 'json')

# files that have "application/..." mimes instead of "text/..."
TEXT_MIMES = ()

# Mimes which are in text, but have a mimetype
PLAINTEXT_MIMES = ('pgp', 'pgp-keys')


def _fix_mimetype(mime: str):
    """
    Translate an old mimetype into one that pygments can
    support

    mime - the mime type to try and find a match for

    Returns - a pygments lexer, or None
    """

    assert '/' in mime, 'Invalid Mimetype'

    mime = mime.lower()
    m_type, m_lang = mime.split('/')

    if m_type == 'text':
        cut = mime[5:]
        if cut in APPLICATION_MIMES:
            return 'application/' + cut

    elif m_type == 'application':
        cut = mime[5:]
        if cut in TEXT_MIMES:
            return 'text/' + cut

    # Easy fixes that we can do manually
    if 'x-c' in m_lang:
        return '{}src'.format(mime)  # Supports C/C++
    elif 'php' in m_lang:
        return 'application/x-php'


def _is_text(mime: str) -> bool:
    """
    Return whether a mime is supported to be plain text or not
    """

    assert '/' in mime, 'Invalid Mimetype'

    m_type, m_format = (f.lower() for f in mime.split('/'))

    if m_type == 'text':
        return True
    elif m_type == 'image':
        return False

    if m_format in PLAINTEXT_MIMES:
        return True

    return False


def get_lexer(mime: str):
    """
    Determine whether or not a mime is supported by pygments

    Returns - A lexer if supported, None if not supported for formatting.
    """

    # Maybe it'll work the first time around?
    try:
        return get_lexer_for_mimetype(mime)
    except ClassNotFound:
        pass  # Oh well

    # Now, let's try and see if we can fix it with some matching
    fixed_mime = _fix_mimetype(mime)

    if fixed_mime:  # Let's try with a matched hack!
        try:
            return get_lexer_for_mimetype(fixed_mime)  # Yay
        except ClassNotFound:
            pass  # Oh well

    # Can well just print it as plaintext?
    if _is_text(mime):
        return get_lexer_for_mimetype('text/plain')  # This lexer does nothing

    # We failed to find anything matching. Let's quit
    return None
